﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace Dotnet.Code.Ext
{
    public static partial class Ext
    {
        public static List<StackInfo> GetStackTraceInfo(this object obj)
        {
            //当前堆栈信息
            StackTrace st = new StackTrace();
            StackFrame[] sfs = st.GetFrames();
            List<StackInfo> list = new List<StackInfo>();
            foreach (System.Diagnostics.StackFrame item in sfs)
            {
                MethodBase method = item.GetMethod();
                string funName = method.Name;
                string clsName = method.DeclaringType.FullName;                
                if (StackFrame.OFFSET_UNKNOWN == item.GetILOffset())
                {
                    break;
                }
                if (funName.Equals("GetStackTraceInfo"))
                    continue;
                if (clsName.StartsWith("System.")) 
                    continue;
                string attr = method.Attributes.ToString().Trim().Trim(',').
                    Replace("PrivateScope,","").Trim().Trim(',').
                    Replace("HideBySig","").Trim().Trim(',');
                string fileName = item.GetFileName();
                int line = item.GetFileLineNumber();
                list.Add(new StackInfo() { ClassName = clsName, FuncName = funName, FuncAttribute= attr, Line = line, FileName = fileName });
            }
            //list =list.Reverse<StackInfo>().ToList();
            return list;
        }
        public static string Stack2String(this List<StackInfo> info,bool isReverse=true)
        {
            if (isReverse == true)
                info = info.Reverse<StackInfo>().ToList();
            StringBuilder sb = new StringBuilder();
            int i = 0;
            foreach(StackInfo item in info)
            {
                sb.Append($"{++i}：类:{item.ClassName} 方法:[{item.FuncAttribute.ToString()}] {item.FuncName}").AppendLine();
            }
            return sb.ToString();
        }
        public class StackInfo
        {
            public string FuncName { get; set; }
            public string FuncAttribute { get; set; }
            //public FunctionType FuncType { get; set; }
            public string ClassName { get; set; }
            public string FileName { get; set; }
            public int Line { get; set; }

        }
    }
}
